﻿///////////////////////////////////////////////////////////////////////////////
// File Name: SkinComboBox.cpp 
// Purpose: SkinComboBox.h 实现文件
// Author: 张东斌、ChongyangLee
// E_Mail: malutianshi7905@sina.com; ChongyangLee@hotmail.com
// History: 
// 2009/10/19 Mod WM_CTLCOLORLISTBOX 消息的返回值
//
///////////////////////////////////////////////////////////////////////////////


#include "stdafx.h"
#include "skincombox.h"
#include "SkinCombolBox.h"
#include "ComboBoxSkin.h"
//#include "InitSKinTK.h"

CSkinCombox::CSkinCombox(void): m_bNewList(false)
{
	m_nComboxState = COMBOX_NORMAL;
	//m_pComboxSkin = GetSkin().GetComboxSkin();
	m_pSubListBox = NULL;
	m_bHistThumb = FALSE;
}

CSkinCombox::~CSkinCombox(void)
{
	HookWindow( (HWND)NULL);
	if((m_bNewList) && (m_pSubListBox))
		delete m_pSubListBox;
}
BOOL CSkinCombox::LoadSkin()
{
    CAutoEnableSkin a(m_bEnableSkin);
	m_pComboxSkin = GetSkin().GetComboxSkin();
    if (!m_pComboxSkin)
    {
        return FALSE;
    }
	SetWindowPos(m_hWnd,NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); 
    return TRUE;
}

BOOL CSkinCombox::InstallSkin(HWND hWnd)
{
    if (!hWnd || !(LoadSkin()))
    {
        return FALSE;
    }
	HookWindow( (HWND)NULL);

	int r = HookWindow( hWnd );

	if(m_pComboxSkin == NULL)
		m_pComboxSkin = GetSkin().GetComboxSkin();

#ifdef _WIN64
	LONG_PTR style = GetWindowLongPtr(m_hWnd, GWL_STYLE);
	LONG_PTR exstyle = GetWindowLongPtr(m_hWnd, GWL_EXSTYLE);
#else
	DWORD style = GetWindowLong(m_hWnd, GWL_STYLE);
	DWORD exstyle = GetWindowLong(m_hWnd, GWL_EXSTYLE);
#endif
	/*if(((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) ||
		((exstyle) & WS_EX_DLGMODALFRAME) )
		m_bBorder = TRUE;
	else
		m_bBorder = FALSE;*/

	m_bHScroll		= style & WS_HSCROLL;
	m_bVScroll		= style & WS_VSCROLL;

	COMBOBOXINFO comboInfo;
	comboInfo.cbSize = sizeof(comboInfo);
	GetComboBoxInfo(m_hWnd,&comboInfo);
	SetWindowPos(m_hWnd,NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); 
    return TRUE;
}
void CSkinCombox::HookComboLBox(HWND hWnd)
{
	m_pSubListBox = static_cast<CSkinCombolBox*>(theHookMap.Lookup(hWnd));
	if(m_pSubListBox == NULL)
	{		
		m_pSubListBox = new CSkinCombolBox;
		m_bNewList = true;

		m_pSubListBox->InstallSkin(hWnd);

		m_pSubListBox->OnNcPaint(NULL);
		
	}
	
}
LRESULT CSkinCombox::OnWndMsg(UINT msg,WPARAM wp,LPARAM lp)
{
	switch(msg)
	{
	case WM_MOUSELEAVE:
		OnMouseLeave();
		return 0;
	case WM_CTLCOLORLISTBOX:
		{
			CComboBox *pComboBox = (CComboBox*)CWnd::FromHandle(m_hWnd);
            CAutoReleaseDC pDC(reinterpret_cast<CWnd*>(pComboBox));
			pDC = pComboBox->GetDC();
			DrawComboBox(pDC);
			if(m_pSubListBox == NULL)
			{
				HookComboLBox((HWND)lp);
			}
			// TODO: 暂时先返回缺省 HBRUSH
			return Default();	
			
		}
	}
	return CSkinWnd::OnWndMsg(msg,wp,lp);
}

void CSkinCombox::OnMouseLeave()
{
	m_nComboxState &= ~COMBOX_PRESSED;
	m_nComboxState &= ~COMBOX_HOVER;

	CComboBox *pComboBox = (CComboBox*)CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(reinterpret_cast<CWnd*>(pComboBox));
	pDC = pComboBox->GetDC();
	DrawComboBox(pDC);
}
void CSkinCombox::OnSetFocus(HWND hWnd)
{
	Default();
	CComboBox *pComboBox = (CComboBox*)CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(reinterpret_cast<CWnd*>(pComboBox));
	pDC = pComboBox->GetDC();
	DrawComboBox(pDC);
}
void CSkinCombox::OnKillFocus(HWND hWnd)
{
	Default();
	CComboBox *pComboBox = (CComboBox*)CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(reinterpret_cast<CWnd*>(pComboBox));
	pDC = pComboBox->GetDC();
	DrawComboBox(pDC);
}
void CSkinCombox::OnSetText(WPARAM wp,LPARAM lp)
{
	Default();
	CComboBox *pComboBox = (CComboBox*)CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(reinterpret_cast<CWnd*>(pComboBox));
	pDC = pComboBox->GetDC();
	DrawComboBox(pDC);
}
void CSkinCombox::OnMouseMove( UINT nFlags, const CPoint& point )
{
	Default();
	if((m_nComboxState == COMBOX_NORMAL) && ((nFlags & MK_LBUTTON) == 0) )
	{
		TRACKMOUSEEVENT tme;
		m_bHistThumb = HitTestThumb(point);
		m_nComboxState |= COMBOX_HOVER;
		tme.cbSize = sizeof(TRACKMOUSEEVENT);
		tme.dwFlags = TME_LEAVE;
		tme.hwndTrack = m_hWnd;
		TrackMouseEvent(&tme);
	}
	else if(nFlags & MK_LBUTTON)
	{
		TRACKMOUSEEVENT tme;
		m_bHistThumb = HitTestThumb(point);
		m_nComboxState |= COMBOX_PRESSED;
		tme.cbSize = sizeof(TRACKMOUSEEVENT);
		tme.dwFlags = TME_LEAVE;
		tme.hwndTrack = m_hWnd;
		TrackMouseEvent(&tme);
	}
	CComboBox *pComboBox = (CComboBox*)CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(reinterpret_cast<CWnd*>(pComboBox));
	pDC = pComboBox->GetDC();
	DrawComboBox(pDC);
}
void CSkinCombox::OnLButtonDown( UINT nFlags , const CPoint& point )
{
	Default();
	m_nComboxState |= COMBOX_PRESSED;
	CComboBox *pComboBox = (CComboBox*)CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(reinterpret_cast<CWnd*>(pComboBox));
	pDC = pComboBox->GetDC();
	DrawComboBox(pDC);
}
void CSkinCombox::OnLButtonUp( UINT nFlags, const CPoint& point )
{
	Default();
	m_nComboxState &= ~COMBOX_PRESSED;
	CComboBox *pComboBox = (CComboBox*)CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(reinterpret_cast<CWnd*>(pComboBox));
	pDC = pComboBox->GetDC();
	DrawComboBox(pDC);
}
void CSkinCombox::OnNcCalcSize( BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
#ifdef _WIN64
	LONG_PTR style = GetWindowLongPtr(m_hWnd, GWL_STYLE);
#else
	DWORD style = GetWindowLong(m_hWnd, GWL_STYLE);
#endif
	m_bHScroll		= style & WS_HSCROLL;
	m_bVScroll		= style & WS_VSCROLL;

	LPRECT lpRect = &(lpncsp->rgrc[0]);
	if(FALSE)
	{
		lpncsp->rgrc[0].left += 1;
		lpncsp->rgrc[0].top += 1;
		lpncsp->rgrc[0].right -= 1;
		lpncsp->rgrc[0].bottom -= 1;

		lpncsp->rgrc[1] = lpncsp->rgrc[0];
	}
}
void CSkinCombox::OnNcPaint(HRGN rgn1)
{
	CComboBox *pComboBox = (CComboBox*)CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(reinterpret_cast<CWnd*>(pComboBox));
	pDC = pComboBox->GetWindowDC();
	//CRect rtWindow;
	//rtWindow.OffsetRect(-rtWindow.left,-rtWindow.top);
	//GetWindowRect(rtWindow);

	//	m_pComboxSkin->DrawImageBorder(pDC,rtWindow,m_pComboxSkin->m_imageBorder);
}
void CSkinCombox::OnPaint()
{
	CComboBox *pComboBox = (CComboBox*)CWnd::FromHandle(m_hWnd);
	
	CPaintDC dc(pComboBox);
	Default(WM_PAINT,(WPARAM)dc.m_hDC,0);
	CAutoReleaseDC pDC(reinterpret_cast<CWnd*>(pComboBox));
	pDC = pComboBox->GetDC();
	DrawComboBox(pDC);

	CRect rtClient;
	GetClientRect(rtClient);
	if(m_pComboxSkin->DrawImageBorder(pDC,rtClient,m_pComboxSkin->m_imageBorder))
	{
		COLORREF color =::GetSysColor(CTLCOLOR_BTN);
		pDC->Draw3dRect(rtClient,color,color);
	}
}
BOOL CSkinCombox::HitTestThumb( const CPoint& point )
{
	CRect rtThumb ;	
	COMBOBOXINFO comboInfo;
	comboInfo.cbSize = sizeof(comboInfo);
	GetComboBoxInfo(m_hWnd,&comboInfo);

	rtThumb = comboInfo.rcButton;

	if(rtThumb.PtInRect(point))
		return TRUE;
	else
		return FALSE;
}
void CSkinCombox::DrawComboBox(CDC *pDC)
{
	if(m_pComboxSkin == NULL)
		return;
	
	CRect rtThumb ;

	COMBOBOXINFO comboInfo;
	comboInfo.cbSize = sizeof(comboInfo);
	GetComboBoxInfo(m_hWnd,&comboInfo);

	rtThumb = comboInfo.rcButton;

	if(m_nComboxState & COMBOX_DISABLED)
	{
		if(!m_pComboxSkin->DrawImageRect(pDC,rtThumb,m_pComboxSkin->m_iamgeThumb[keCheckPressed]))
			m_pComboxSkin->DrawImageRect(pDC,rtThumb,m_pComboxSkin->m_iamgeThumb[keCheckNormal]);
	}
	if(m_nComboxState & COMBOX_PRESSED)
	{
		if(!m_pComboxSkin->DrawImageRect(pDC,rtThumb,m_pComboxSkin->m_iamgeThumb[keCheckPressed]))
			m_pComboxSkin->DrawImageRect(pDC,rtThumb,m_pComboxSkin->m_iamgeThumb[keCheckNormal]);
	}
	else if(m_nComboxState & COMBOX_HOVER)
	{
		if(!m_pComboxSkin->DrawImageRect(pDC,rtThumb,m_pComboxSkin->m_iamgeThumb[keCheckHover]))
			m_pComboxSkin->DrawImageRect(pDC,rtThumb,m_pComboxSkin->m_iamgeThumb[keCheckNormal]);
	}
	else
		m_pComboxSkin->DrawImageRect(pDC,rtThumb,m_pComboxSkin->m_iamgeThumb[keCheckNormal]);

}
